using System.Collections.Generic;
using UnityEngine;

namespace Share
{
    public class ObjectPoolManager : SingletonMonoObject<ObjectPoolManager>
    {
        private Dictionary<string, Queue<GameObject>> poolDictionary = new Dictionary<string, Queue<GameObject>>();
        private Dictionary<string, Queue<AudioClip>> audioClipPool = new Dictionary<string, Queue<AudioClip>>();

        public void CreatePool(GameObject prefab, int poolSize)
        {
            if (prefab == null)
            {
                XKLog.LogError("Prefab is null.");
                return;
            }

            string poolKey = prefab.name;
            if (poolDictionary.ContainsKey(poolKey))
            {
                XKLog.LogWarning($"Pool for {poolKey} already exists.");
                return;
            }

            Queue<GameObject> objectPool = new Queue<GameObject>();

            for (int i = 0; i < poolSize; i++)
            {
                GameObject obj = Instantiate(prefab);
                obj.SetActive(false);
                obj.name = poolKey;
                // 添加ObjectPoolItem组件并初始化
                var poolItem = obj.GetOrAddComponent<ObjectPoolItem>();
                obj.transform.SetParent(GameRootManager.Instance.GetPoolRoot());
                objectPool.Enqueue(obj);
            }

            poolDictionary[poolKey] = objectPool;
        }

        public AudioClip GetFreeAudioClipFromPool(AudioClip clip)
        {
            if (clip == null)
            {
                XKLog.LogError("AudioClip is null.");
                return null;
            }

            string clipKey = clip.name;
            if (!audioClipPool.ContainsKey(clipKey))
            {
                audioClipPool[clipKey] = new Queue<AudioClip>();
            }

            if (audioClipPool[clipKey].Count > 0)
            {
                return audioClipPool[clipKey].Dequeue();
            }

            // 如果池中没有可用clip，创建一个新的并加入到池中
            AudioClip newClip = Instantiate(clip);
            audioClipPool[clipKey].Enqueue(newClip);

            // 从池中获取一个可用的clip
            return audioClipPool[clipKey].Dequeue();
        }

        public void ReturnAudioClipToPool(AudioClip clip)
        {
            if (clip == null)
            {
                XKLog.LogError("AudioClip is null.");
                return;
            }

            string clipKey = clip.name;
            if (!audioClipPool.ContainsKey(clipKey))
            {
                audioClipPool[clipKey] = new Queue<AudioClip>();
            }

            audioClipPool[clipKey].Enqueue(clip);
        }

        public GameObject GetObject(GameObject prefab)
        {
            if (prefab == null)
            {
                XKLog.LogError("Prefab is null.");
                return null;
            }

            string poolKey = prefab.name;
            if (!poolDictionary.ContainsKey(poolKey))
            {
                CreatePool(prefab, 5);
            }

            Queue<GameObject> objectPool = poolDictionary[poolKey];

            // 从池中查找非Active的节点
            GameObject objToReuse = null;
            int checkCount = objectPool.Count;

            for (int i = 0; i < checkCount; i++)
            {
                GameObject candidate = objectPool.Dequeue();
                if (!candidate.activeInHierarchy)
                {
                    objToReuse = candidate;
                    break;
                }
                else
                {
                    // 如果对象是Active的，重新放回队列末尾
                    objectPool.Enqueue(candidate);
                }
            }

            // 如果没有找到非Active的节点，创建新对象并加入到对象池
            if (objToReuse == null)
            {
                objToReuse = Instantiate(prefab);
                objToReuse.name = poolKey;
                // 添加ObjectPoolItem组件并初始化
                var poolItem = objToReuse.GetOrAddComponent<ObjectPoolItem>();
                objToReuse.transform.SetParent(GameRootManager.Instance.GetPoolRoot());
                // 将新创建的对象加入到对象池中，供后续重用
                objectPool.Enqueue(objToReuse);
            }

            ResetParticleSystem(objToReuse);
            objToReuse.SetActive(true);
            return objToReuse;
        }

        public void ReturnObject(GameObject obj)
        {
            if (obj == null)
            {
                XKLog.LogError("Object is null.");
                return;
            }

            string poolKey = obj.name;
            if (!poolDictionary.ContainsKey(poolKey))
            {
                XKLog.LogError($"Pool for {poolKey} does not exist.");
                Destroy(obj);
                return;
            }

            // 先设置父级，再放入队列
            obj.transform.SetParent(GameRootManager.Instance.GetPoolRoot());
            poolDictionary[poolKey].Enqueue(obj);

            // 最后设置为非激活状态，避免触发OnDisable时的递归调用
            obj.SetActive(false);
        }

        private void ResetParticleSystem(GameObject obj)
        {
            ParticleSystem[] particleSystems = obj.GetComponentsInChildren<ParticleSystem>();
            foreach (ParticleSystem ps in particleSystems)
            {
                ps.Stop();
                ps.Clear();
                ps.Play();
            }
        }

        public bool IsPooledObject(GameObject gameObject)
        {
            if (gameObject == null)
            {
                XKLog.LogWarning("IsPooledObject: gameObject is null");
                return false;
            }

            string poolKey = gameObject.name;
            if (!poolDictionary.ContainsKey(poolKey))
            {
                return false;
            }

            // 检查对象池中是否包含该对象
            return poolDictionary[poolKey].Contains(gameObject);
        }
    }
}
